package com.ljchen.formalProject.frame.shiro.realm;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ljchen.formalProject.enums.ResultCode;
import com.ljchen.formalProject.frame.exceptions.APIException;
import com.ljchen.formalProject.model.po.User;
import com.ljchen.formalProject.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

@Slf4j
public class UsernamePasswordRealm extends AuthenticatingRealm {

    @Autowired
    private UserService userService;

    /**
     * 告诉token，当token类型为UsernamePasswordToken时，通过这个Realm来进行校验
     *
     * @param token 令牌
     * @return boolean
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }

    /**
     * 配置加密规则
     * 这里的加密规则必须和注册时的加密规则一致
     *
     * @param credentialsMatcher 凭证匹配器
     */
    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        HashedCredentialsMatcher hashedCredentialsMatcher=new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        hashedCredentialsMatcher.setHashIterations(5);
        super.setCredentialsMatcher(hashedCredentialsMatcher);
    }

    /**
     * 验证用户登陆时的用户名和密码
     *
     * @param authenticationToken 身份验证令牌
     * @return {@link AuthenticationInfo}
     * @throws AuthenticationException 身份验证异常
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken) authenticationToken;
        LambdaQueryWrapper<User> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername,usernamePasswordToken.getUsername());
        User user=userService.getOne(wrapper);
        if (ObjectUtil.isNull(user)) {
            throw new APIException(ResultCode.ERROR,"该用户不存在");
        }
        String salt=user.getSalt();
        SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), ByteSource.Util.bytes(salt),this.getName());
        return simpleAuthenticationInfo;
    }
}
